﻿Imports System.Collections
Imports System.Collections.Generic
Imports System.Drawing

Public Class Raster
    Inherits PictureBox

#Region "Private declarations"

    Private _aantalRijen As Integer
    Private _aantalKolommen As Integer
    Private _selection(,) As Boolean
    Private _cellWidth As Integer
    Private _cellHeight As Integer
    Private _prevRow As Integer = -1
    Private _prevColumn As Integer = -1
    Private _mouseButtonDown As Boolean = False

#End Region

#Region "Property's"

    Public Property AantalRijen() As Integer
        Get
            Return _aantalRijen
        End Get
        Set(ByVal value As Integer)
            _aantalRijen = value
            _cellHeight = (Me.Height - 1) \ value
            If (_aantalRijen > 0 AndAlso _aantalKolommen > 0) Then
                _selection = New Boolean(_aantalRijen - 1, _aantalKolommen - 1) {}
            End If
            Invalidate()
        End Set
    End Property

    Public Property AantalKolommen() As Integer
        Get
            Return _aantalKolommen
        End Get
        Set(ByVal value As Integer)
            _aantalKolommen = value
            _cellWidth = (Me.Width - 1) \ value
            If (_aantalRijen > 0 AndAlso _aantalKolommen > 0) Then
                _selection = New Boolean(_aantalRijen - 1, _aantalKolommen - 1) {}
            End If
            Invalidate()
        End Set
    End Property

    Public Property Selection(ByVal row As Integer, ByVal column As Integer) As Boolean
        Get
            If (_selection Is Nothing OrElse Not Me.ValidCoordinates(row, column)) Then Return False
            Return _selection(row, column)
        End Get
        Set(ByVal value As Boolean)
            If (_selection Is Nothing OrElse Not Me.ValidCoordinates(row, column)) Then Return
            _selection(row, column) = value
            RaiseEvent SelectionChanged(Me, EventArgs.Empty)
        End Set
    End Property

    Public Event SelectionChanged(ByVal sender As Object, ByVal e As EventArgs)

#End Region

#Region "Constructor"

    Public Sub New()
        Me.Margin = New Padding(0)
        Me.Padding = New Padding(0)
        Me.AutoSize = False
        Me.Cursor = Cursors.Hand
    End Sub

#End Region

#Region "Event handlers"

    Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
        MyBase.OnResize(e)
        _cellHeight = (Me.Height - 1) \ _aantalRijen
        _cellWidth = (Me.Width - 1) \ _aantalKolommen
        Invalidate()
    End Sub

    Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseDown(e)
        If (_mouseButtonDown) Then Return
        _mouseButtonDown = True
        _prevRow = e.Y \ _cellHeight
        _prevColumn = e.X \ _cellWidth
    End Sub

    Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseUp(e)
        If Not _mouseButtonDown Then Return
        _mouseButtonDown = False
        Dim row As Integer = e.Y \ _cellHeight
        Dim column As Integer = e.X \ _cellWidth
        If Not (row = _prevRow AndAlso column = _prevColumn) Then Return
        If (ValidCoordinates(row, column)) Then
            Dim gr As Graphics = Me.CreateGraphics()
            Toggle(row, column, gr)
        End If
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
        For row As Integer = 0 To AantalRijen
            'horizontale lijnen
            Dim pen As New Pen(SystemColors.ButtonShadow)
            e.Graphics.DrawLine(pen, 0, row * _cellHeight, AantalKolommen * _cellWidth, row * _cellHeight)
            If row = AantalRijen Then Continue For
            pen.Color = SystemColors.ControlLightLight
            e.Graphics.DrawLine(pen, 0, row * _cellHeight - 1, AantalKolommen * _cellWidth, row * _cellHeight - 1)
        Next
        For column As Integer = 0 To AantalKolommen
            'vertikale lijnen
            Dim pen As New Pen(SystemColors.ButtonShadow)
            e.Graphics.DrawLine(pen, column * _cellWidth, 0, column * _cellWidth, AantalRijen * _cellHeight)
            If column = AantalKolommen Then Continue For
            pen.Color = SystemColors.ControlLightLight
            e.Graphics.DrawLine(pen, column * _cellWidth - 1, 0, column * _cellWidth - 1, AantalRijen * _cellHeight)
        Next
        PaintRaster(e.Graphics)
    End Sub

#End Region

#Region "Public methods"

    Public Sub SelecteerAlles()
        For row As Integer = 0 To _aantalRijen - 1
            For column As Integer = 0 To _aantalKolommen - 1
                _selection(row, column) = True
            Next
        Next
        RaiseEvent SelectionChanged(Me, EventArgs.Empty)
        Invalidate()
    End Sub

    Public Sub SelecteerNiets()
        For row As Integer = 0 To _aantalRijen - 1
            For column As Integer = 0 To _aantalKolommen - 1
                _selection(row, column) = False
            Next
        Next
        RaiseEvent SelectionChanged(Me, EventArgs.Empty)
        Invalidate()
    End Sub

#End Region

#Region "Private methods"

    Private Sub PaintRaster(ByVal gr As Graphics)
        For row As Integer = 0 To AantalRijen - 1
            For column As Integer = 0 To AantalKolommen - 1
                PaintCell(row, column, gr)
            Next
        Next
    End Sub

    Private Sub PaintCell(ByVal row As Integer, ByVal column As Integer, ByVal gr As Graphics)
        Dim br As Brush = GetBrush(row, column, gr)
        gr.FillRectangle(br, column * _cellWidth + 2, row * _cellHeight + 2, _cellWidth - 3, _cellHeight - 3)
    End Sub

    Private Function GetBrush(ByVal row As Integer, ByVal column As Integer, ByVal gr As Graphics) As Brush
        Dim br As Brush = SystemBrushes.Control
        If (Selection(row, column)) Then br = SystemBrushes.ControlDark
        Return br
    End Function

    Private Sub Toggle(ByVal row As Integer, ByVal column As Integer, ByVal gr As Graphics)
        If (ValidCoordinates(row, column)) Then
            Selection(row, column) = Not Selection(row, column)
            PaintCell(row, column, gr)
        End If
    End Sub

    Private Function ValidCoordinates(ByVal row As Integer, ByVal column As Integer) As Boolean
        Return (row >= 0 And column >= 0 And row < AantalRijen And column < AantalKolommen)
    End Function

#End Region

End Class
